package com.zzyq.pc.common.plugin.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zzyq.pc.web.user.model.Permission;
import com.zzyq.pc.web.user.model.Role;
import com.zzyq.pc.web.user.model.User;
import com.zzyq.pc.web.user.service.IUserService;

/**
 * Shiro自定义域
 * 
 * @author sywd
 *
 */
@Component
public class MonitorRealm extends AuthorizingRealm {
    private final Logger log = Logger.getLogger(MonitorRealm.class);
    @Autowired
    private IUserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 角色集合
        Set<String> roleSet = new HashSet<>();
        // 权限集合
        Set<String> permissionSet = new HashSet<>();
        // 获取帐号信息
        User user = TokenManager.getUser();
        // 新建一个身份
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 根据帐号查询角色
        List<Role> roles = userService.findRoles(user.getUserId());
        for (Role role : roles) {
            roleSet.add(role.getRoleEnum());
        }
        authorizationInfo.addRoles(roleSet);
        user.setRoles(roles);
        // 查询权限
        List<Permission> permissions = userService.findPermissions(user.getUserId());
        for (Permission permission : permissions) {
            permissionSet.add(permission.getPermissionEnum());
        }
        authorizationInfo.addStringPermissions(permissionSet);
        user.setPermissions(permissions);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        ZzyqToken authToken = (ZzyqToken) token;
        // 获取帐号信息
        String account = (String) authToken.getPrincipal();
        // 在数据库中查找帐号信息
        User user = userService.findUserByAccount(account);
        // 判断帐号信息并抛出错误帐号的相应异常
        if (user == null) {
            log.debug("数据库中未找到名为[ " + account + " ]的帐号");
            throw new UnknownAccountException();
        } else if (user.getIsDelete() == 1) {
            log.debug("数据库中名为[ " + account + " ]的帐号已被删除并锁定");
            throw new LockedAccountException();
        }
        List<Role> roles = userService.findRoles(user.getUserId());
        user.setRoles(roles);
        List<Permission> permissions = userService.findPermissions(user.getUserId());
        user.setPermissions(permissions);
        // 交由Realm验证帐号是否正确
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUserSalt());
        return new SimpleAuthenticationInfo(user, user.getUserPwd(), credentialsSalt, getName());
    }

    /**
     * 清空当前用户权限信息
     */
    public void clearCachedAuthorizationInfo() {
        PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
        super.clearCachedAuthorizationInfo(principals);
    }

    /**
     * 指定principalCollection 清除
     */
    public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principalCollection, getName());
        super.clearCachedAuthorizationInfo(principals);
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

}
